/***************************************************************************
 *   Copyright (C) 2007 by Warren Kenny   				   *
 *   warren.kenny@gmail.com   						   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#ifndef GSARRAY_H
#define GSARRAY_H

#include <gsCore/gsCore.h>
#include <gsCore/gsException.h>

#include <gsContainer/gsContainer.h>


template<class T>
class gsArray : public gsContainer<T>
{
	
public:
	
	///
	///	Constructor(s)
	///
	
	/**
	 *	Default constructor
	 */
	inline gsArray();
	
	/**
	 * 	Constructor which specifies the initial capacity of the array 
	 * @param capacity The initial capacity of the array
	 */
	inline gsArray( const gsUInt capacity );
	
	/**
	 * 	Constructor which specifies the initial capacity of the array 
	 * @param capacity The initial capacity of the array
	 */
	inline gsArray( const gsContainer<T>& container );
	
	/**
	 * 	Generic method for inserting an object into the container, overridden from gsContainer
	 * @param object The object to be inserted
	 * @return 	- True is the object was successfully inserted
	 *		- False otherwise
	 */
	inline virtual gsBool insert( const T& object );
		
	/**
	 * 	Generic method for removing all instances of \a object from the container, overridden from gsContainer
	 *	Note: for gsArray, this may case the array's contents to be shunted 
	 * @param object The object to be removed
	 * @return 	- True if the object was found and removed successfully
	 *		- False otherwise
	 */
	inline virtual gsBool remove( const T& object );
		
	/**
	 * 	Generic function for indicating whether a given object exists within the container, overridden from gsContainer
	 * @param object The object to be found
	 * @return 	- True if the object was found
	 *		- False otherwise
	 */
	inline virtual gsBool find( const T& object );
	
	/**
	 *        Generic function for retrieving an object from the specified index within the container, overridden from gsContainer
	 * @param index The index within the container from which the object should be retrieved
	 * @param object A reference to the object to be set
	 * @return 	- True if the object was retrieved
	 *		- False otherwise
	 */
	inline virtual gsBool get( const gsUInt index, T& object );
	
	/**
	 *	Generic function for indicating whether the container is empty
	 * @return 	- True if the container is empty
	 *		- False if the container holds one or more objects
	 */
	inline virtual gsBool empty();

	/**
	 *	Generic function for finding the number of elements in the container, overridden from gsContainer
	 * @return	The number of elements in the container 
	 */
	inline virtual const gsUInt getSize();
	
	/**
	 *        Generic function for finding the current storage capacity of the container, overridden from gsContainer
	 * @return 	The current storage capacity of the container
	 */
	inline virtual const gsUInt getCapacity();
	
	/**
	 * 	Destructs all objects in the array and deletes the array's storage buffer
	 */
	inline virtual void clear();
	
	/**
	 * 	Sets the capacity to the value specified by newCapacity; if newCapacity is smaller than the current capacity of the
	 * 	array, some contained objects may be lost
	 * @param newCapacity The new capacity of the array
	 */
	inline void setCapacity( const gsUInt newCapacity );
	
	/**
	 * 	Overloaded operator; allows for retrieval of objects from the specified array index
	 * @param arrayIndex The index where the object should be retrieved from
	 * @return The object
	 */
	inline T& operator[]( const gsUInt arrayIndex ) throw( gsArrayIndexOutOfBoundsException );
	
	/**
	 * 	Overloaded operator; allows for const access to objects 
	 * @param arrayIndex The index where the object should be retrieved from
	 * @return The object
	 */
	inline const T& operator[]( const gsUInt arrayIndex ) const throw( gsArrayIndexOutOfBoundsException );
	
	/**
	 *        Overloaded operator; allows the contents of another gsContainer to be copied into this gsArray
	 * @param array The other container
	 * @return A reference to the new gsArray
	 */
	inline T& operator=( gsContainer<T> &container );
	
	/**
	 * 	Default destructor
	 */
	~gsArray();

protected:
	
	inline void expand();
	
	/**
	 * 	Resizes the array to the specified new size, copying old objects into the new buffer
	 * @param newSize 
	 */
	inline void resize( gsUInt newSize );
		
	/**
	 * 	Resizes the array to the specified new size without preserving old objects
	 * @param newSize 
	 */
	inline void resizeNoPreserve( gsUInt newSize );
	
private:
		
	// Pointer to the object buffer
	T* m_objects;
	
	// The number of objects in the container
	gsUInt m_size;
	
	// The allocated capacity of this container
	gsUInt m_capacity;
};

#include <gsContainer/gsArray.inl>

#endif
